﻿using System;
using Castle.Core.Interceptor;

namespace Trentacular.SharePoint.Deployment.Data.Proxy
{
    public abstract class BaseLazyInitializer<T> : BaseLazyInitializer
    {
        public override Type TargetType
        {
            get { return typeof(T); }
        }
    }

    public abstract class BaseLazyInitializer : ILazyInitializer, IInterceptor
    {
        protected virtual object Target { get; set; }

        protected static readonly object InvokeImplementation = new object();

        protected bool IsInitialized { get; set; }

        #region ILazyInitializer Members

        public void EnsureInitialized()
        {
            if (!IsInitialized)
            {
                Target = InitializeTarget();
                IsInitialized = true;
            }
        }

        /// <summary>
        /// Return the Underlying Persistent Object, initializing if necessary.
        /// </summary>
        /// <returns>The Persistent Object this proxy is Proxying.</returns>
        public virtual object GetImplementation()
        {
            EnsureInitialized();
            return Target;
        }

        public abstract Type TargetType
        {
            get;
        }

        #endregion

        #region IInterceptor Members

        public virtual void Intercept(IInvocation invocation)
        {
            invocation.ReturnValue = Invoke(invocation);

            if (invocation.ReturnValue == InvokeImplementation)
                invocation.ReturnValue = invocation.Method.Invoke(GetImplementation(), invocation.Arguments);
        }

        #endregion

        protected abstract object InitializeTarget();

        protected abstract object Invoke(IInvocation invocation);
    }
}
